package com.smart.community.work.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.work.dto.StaffQueryDTO;
import com.smart.community.work.mapper.StaffMapper;
import com.smart.community.work.service.StaffService;
import com.smart.community.work.vo.StaffVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;

/**
 * 员工管理Service实现类
 * 基于用户表和用户物业公司关联表实现员工管理
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StaffServiceImpl implements StaffService {

    private final StaffMapper staffMapper;

    @Override
    public IPage<StaffVO> selectStaffPage(Page<StaffVO> page, StaffQueryDTO queryDTO, Long currentUserId) throws Exception {
        log.info("分页查询员工列表，当前页：{}，页大小：{}，查询条件：{}", page.getCurrent(), page.getSize(), queryDTO);
        
        // 数据权限检查：确保只能查看当前登录者关联的物业公司的用户
        validatePropertyCompanyPermission(queryDTO, currentUserId);
        
        log.info("查询参数中的物业公司ID列表：{}", Arrays.toString(queryDTO.getPropertyCompanyIds()));
        
        // 执行查询
        IPage<StaffVO> result = staffMapper.selectStaffPage(page, queryDTO, currentUserId);
        
        log.info("查询结果记录数：{}", result.getRecords().size());
        
        // 检查每条记录的物业公司名称
        result.getRecords().forEach(staff -> {
            log.info("员工：{}，物业公司ID：{}，物业公司名称：{}", 
                    staff.getRealName(), staff.getPropertyCompanyId(), staff.getPropertyCompanyName());
        });
        
        return result;
    }
    
    /**
     * 验证物业公司权限
     * 确保用户只能查看自己有权限的物业公司的员工
     */
    private void validatePropertyCompanyPermission(StaffQueryDTO queryDTO, Long currentUserId) throws Exception {
        // 获取当前用户关联的物业公司ID列表
        List<Long> userPropertyCompanyIds = getUserPropertyCompanyIds(currentUserId);
        
        if (userPropertyCompanyIds == null || userPropertyCompanyIds.isEmpty()) {
            log.warn("用户{}没有关联任何物业公司，无法查询员工列表", currentUserId);
            throw new BusinessException("您没有关联任何物业公司，无法查看员工信息");
        }
        
        // 如果查询条件中指定了物业公司ID，验证权限
        if (queryDTO.getPropertyCompanyIds() != null && queryDTO.getPropertyCompanyIds().length > 0) {
            List<Long> requestedIds = Arrays.asList(queryDTO.getPropertyCompanyIds());
            
            // 检查请求的物业公司ID是否都在用户权限范围内
            boolean hasPermission = userPropertyCompanyIds.containsAll(requestedIds);
            if (!hasPermission) {
                log.warn("用户{}请求的物业公司ID{}不在其权限范围内{}", currentUserId, requestedIds, userPropertyCompanyIds);
                throw new BusinessException("您没有权限查看指定物业公司的员工信息");
            }
            
            log.info("用户{}查询物业公司{}的员工列表，权限验证通过", currentUserId, requestedIds);
        } else {
            // 如果没有指定物业公司ID，使用用户有权限的所有物业公司ID
            Long[] allowedIds = userPropertyCompanyIds.toArray(new Long[0]);
            queryDTO.setPropertyCompanyIds(allowedIds);
            log.info("用户{}未指定物业公司ID，使用其有权限的所有物业公司ID：{}", currentUserId, Arrays.toString(allowedIds));
        }
    }
    
    /**
     * 获取用户关联的物业公司ID列表
     */
    private List<Long> getUserPropertyCompanyIds(Long userId) throws Exception {
        try {
            log.info("获取用户{}关联的物业公司ID列表", userId);
            
            // 通过StaffMapper查询用户关联的物业公司ID
            List<Long> propertyCompanyIds = staffMapper.getUserPropertyCompanyIds(userId);
            
            if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
                log.warn("用户{}没有关联任何物业公司", userId);
                return new ArrayList<>();
            }
            
            log.info("用户{}关联的物业公司ID列表：{}", userId, propertyCompanyIds);
            return propertyCompanyIds;
            
        } catch (Exception e) {
            log.error("获取用户{}关联的物业公司ID列表失败", userId, e);
            throw new BusinessException("获取用户权限信息失败");
        }
    }

    @Override
    public StaffVO getStaffById(Long staffId, Long propertyCompanyId, Long currentUserId) throws Exception {
        log.info("查询员工详情，员工ID：{}，物业公司ID：{}，当前用户ID：{}", staffId, propertyCompanyId, currentUserId);
        
        StaffVO staff = staffMapper.selectStaffById(staffId, propertyCompanyId, currentUserId);
        if (staff == null) {
            throw new BusinessException("员工不存在或无权限查看");
        }
        
        return staff;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addStaff(StaffQueryDTO staffDTO, Long currentUserId) throws Exception {
        log.info("添加员工到物业公司，员工信息：{}，当前用户ID：{}", staffDTO, currentUserId);
        
        // 参数验证
        if (!StringUtils.hasText(staffDTO.getRealName())) {
            throw new BusinessException("员工姓名不能为空");
        }
        if (!StringUtils.hasText(staffDTO.getPhone())) {
            throw new BusinessException("手机号不能为空");
        }
        if (staffDTO.getPropertyCompanyIds() == null || staffDTO.getPropertyCompanyIds().length == 0) {
            throw new BusinessException("物业公司ID不能为空");
        }
        
        // 这里应该调用用户服务创建用户，然后创建用户物业公司关联
        // 由于涉及到用户创建，这里简化处理，假设用户已存在
        // 实际实现中应该：
        // 1. 检查用户是否存在（根据手机号或邮箱）
        // 2. 如果不存在，创建用户
        // 3. 创建用户物业公司关联
        
        // 暂时返回模拟的用户ID
        Long userId = System.currentTimeMillis() % 1000000; // 模拟用户ID
        
        log.info("添加员工成功，用户ID：{}", userId);
        return userId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStaff(Long staffId, StaffQueryDTO staffDTO, Long currentUserId) throws Exception {
        log.info("更新员工信息，员工ID：{}，员工信息：{}，当前用户ID：{}", staffId, staffDTO, currentUserId);
        
        // 检查员工是否存在
        StaffVO existingStaff = staffMapper.selectStaffById(staffId, null, currentUserId);
        if (existingStaff == null) {
            throw new BusinessException("员工不存在");
        }
        
        // 权限检查：检查当前用户是否有权限修改该员工
        // 这里可以添加更详细的权限检查逻辑
        
        // 这里应该调用用户服务更新用户信息，然后更新用户物业公司关联
        // 由于涉及到用户更新，这里简化处理
        // 实际实现中应该：
        // 1. 更新用户基本信息
        // 2. 更新用户物业公司关联信息
        
        log.info("更新员工信息成功，员工ID：{}", staffId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStaff(Long staffId, Long currentUserId) throws Exception {
        log.info("从物业公司移除员工，员工ID：{}，当前用户ID：{}", staffId, currentUserId);
        
        // 检查员工是否存在
        StaffVO existingStaff = staffMapper.selectStaffById(staffId, null, currentUserId);
        if (existingStaff == null) {
            throw new BusinessException("员工不存在");
        }
        
        // 权限检查：检查当前用户是否有权限删除该员工
        // 这里可以添加更详细的权限检查逻辑
        
        // 这里应该更新用户物业公司关联状态为离职
        // 实际实现中应该：
        // 1. 更新用户物业公司关联状态为离职（status = 0）
        // 2. 记录离职时间
        
        log.info("从物业公司移除员工成功，员工ID：{}", staffId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStaffStatus(Long staffId, Integer status, Long currentUserId) throws Exception {
        log.info("更新员工状态，员工ID：{}，状态：{}，当前用户ID：{}", staffId, status, currentUserId);
        
        // 检查员工是否存在
        StaffVO existingStaff = staffMapper.selectStaffById(staffId, null, currentUserId);
        if (existingStaff == null) {
            throw new BusinessException("员工不存在");
        }
        
        // 权限检查：检查当前用户是否有权限修改该员工状态
        // 这里可以添加更详细的权限检查逻辑
        
        // 这里应该更新用户物业公司关联状态
        // 实际实现中应该：
        // 1. 更新用户物业公司关联状态
        // 2. 如果状态为离职，记录离职时间
        
        log.info("更新员工状态成功，员工ID：{}，状态：{}", staffId, status);
    }

    @Override
    public List<StaffVO> searchStaff(StaffQueryDTO queryDTO, Long currentUserId) throws Exception {
        log.info("搜索员工，查询条件：{}，当前用户ID：{}", queryDTO, currentUserId);
        
        return staffMapper.searchStaff(queryDTO, currentUserId);
    }
}